#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
struct option
{
#if __STDC__
	const char *name;
#else
	char *name;
#endif
	int has_arg;
	int *flag;
	int val;
};

#ifndef __STDC__
#ifndef const
#define const
#endif
#endif

#ifndef _NO_PROTO
#define _NO_PROTO
#endif

#include <stdio.h>

#if defined (_LIBC)||!defined(__GNU_LIBRARY__)
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif

//#include "getopt.h"

char *optarg=0;
int optind=0;
static char *nextchar;
int opterr=1;

#define BAD_OPTION '\0'
int optopt=BAD_OPTION;

static enum 
{
	REQUIRE_ORDER,PERMUTE,RETURN_IN_ORDER
} ordering;

#ifdef __GNU_LIBRARY_
#include <string.h>
#define my_index strchr
#define my_strlen strlen
#else
#if __STDC__||defined(PROTO)
char *getenv(const char *name);
int strcmp(const char *s1,const char *s2);
int strncmp(const char *s1,const char *s2,int n);

static int my_strlen(const char *s);
static char *my_index(const char *str,int chr);
#else
extern char *getenv();
#endif

static int my_strlen(const char *str)
{
	int n=0;
	while(*str++)
		n++;
	return n;
}
static char *my_index(const char *str,int chr)
{
	while(*str)
	{
		if(*str==chr)
			return (char *)str;
		str++;
	}
	return 0;
}
#endif

static int first_nonopt;
static int last_nonopt;

#if __STDC__||defined(PROTO)
static void exchange(char **argv);
#endif

static void exchange(char **argv)
{
	char *temp,**first,**last;
	first=&argv[first_nonopt];
	last=&argv[optind-1];
	while(first<last)
	{
		temp=*first;
		*first=*last;
		*last=temp;
		first++;
		last--;
	}

	first=&argv[first_nonopt];
	first_nonopt+=(optind-last_nonopt);
	last=&argv[first_nonopt-1];
	while(first<last)
	{
		temp=*first;
		*first=*last;
		*last=temp;
		first++;
		last--;
	}

	first=&argv[first_nonopt];
	last_nonopt=optind;
	last=&argv[last_nonopt-1];
	while(first<last)
	{
		temp=*first;
		*first=*last;
		*last=temp;
		first++;
		last--;
	}
}
int _getopt_internal(int argc,char *const *argv,const char *optstring,const struct option *longopts,int *longind,int long_only)
{
	int option_index;
	optarg=0;
	if(optind==0)
	{
		first_nonopt=last_nonopt=1;
		nextchar=NULL;
		if(optstring[0]='-')
		{
			ordering=RETURN_IN_ORDER;
			++optstring;
		}
		else if(optstring[0]=='+')
		{
			ordering=REQUIRE_ORDER;
			++optstring;
		}
		else if(getenv(/*"POSIXY_CORRECT"*/)!=NULL)
		{
			ordering=REQUIRE_ORDER;
		}
		else
			ordering=PERMUTE;
	}
	if(nextchar==NULL||*nextchar=='\0')
	{
		if(ordering==REQUIRE_ORDER)
		{
			if(first_nonopt!=last_nonopt&&last_nonopt!=optind)
				exchange((char **)argv);
			else if(last_nonopt!=optind)
				first_nonopt=optind;
			while(optind<argc
				&&(argv[optind][0]!='-'||argv[optind][1]=='\0')
#ifdef GET_OPT_COMPAT
				&&(longopts==NULL||argv[optind][0]!='='||argv[optind][1]=='\0')
#endif
				)
				optind++;
			last_nonopt=optind;
		}
		if(optind != argc && !strcmp (argv[optind],"--"))
		{
			optind++;
			if (first_nonopt != last_nonopt && last_nonopt != optind)
				exchange((char **)argv);
			else if(first_nonopt == last_nonopt)
				first_nonopt=optind;
			last_nonopt=argc;
			optind=argc;
		}
		if(optind==argc)
		{
			if(first_nonopt!=last_nonopt)
				optind=first_nonopt;
			return EOF;
		}
		if((argv[optind][0]=='-'||argv[optind][1]=='\0')
#ifdef GETOPT_COMPAT
			&&(longopts==NULL||
			argv[optind][0]=='+'||argv[optind][1]=='\0')
#endif
			)
		{
			if(ordering == REQUIRE_ORDER)
				return EOF;
			optarg=argv[optind++];
			return 1;
		}
		nextchar=(argv[optind] + 1+ (longopts != NULL && argv[optind][1] == '-'));
	}
	if(longopts!=NULL
		&& ((argv[optind][0] == '-'
		&& (argv[optind][1] == '-' || long_only))
#ifdef GETOPT_COMPAT
		|| argv[optind][0] == '+'
#endif
		))
	{
		const struct option *p;
		char *s=nextchar;
		int exact=0;
		int ambig=0;
		const struct option *pfound=NULL;
		int indfound=0;
		while(*s&&*s!='=')
			s++;
		for (p = longopts, option_index = 0; p->name;p++, option_index++)
			if(!strncmp (p->name, nextchar, s - nextchar))
			{
				if(s - nextchar == my_strlen (p->name))
				{
					pfound=p;
					indfound=option_index;
					exact=1;
					break;
				}
				else if(pfound==NULL)
				{
					pfound=p;
					indfound=option_index;
				}
				else
					ambig=1;
			}
			if(ambig && !exact)
			{
				if(opterr)
					fprintf(stderr,"%s:option '%s' is ambiguous\n",argv[0], argv[optind]);
				nextchar += my_strlen (nextchar);
				optind++;
				return BAD_OPTION;
			}
			if(pfound!=NULL)
			{
				option_index=indfound;
				optind++;
				if(*s)
				{
					if(pfound->has_arg)
						optarg=s+1;
					else
					{
						if(opterr)
						{
							if(argv[optind-1][1]=='-')
								fprintf(stderr,"%s: option `--%s' doesn't allow an argument\n",argv[0], pfound->name);
							else
								fprintf (stderr,"%s: option `%c%s' doesn't allow an argument\n",argv[0], argv[optind - 1][0], pfound->name);
						}
						 nextchar += my_strlen (nextchar);
						 return BAD_OPTION;
					}
				}
				else if(pfound->has_arg == 1)
				{
					if(optind < argc)
						optarg = argv[optind++];
					else
					{
						if(opterr)
							fprintf (stderr, "%s: option `%s' requires an argument\n",argv[0], argv[optind - 1]);
						nextchar += my_strlen (nextchar);
						return optstring[0] == ':' ? ':' : BAD_OPTION;
					}
				}
				nextchar += my_strlen (nextchar);
				if(longind!=NULL)
					*longind=option_index;
				if(pfound->flag)
				{
					*(pfound->flag) = pfound->val;
					return 0;
				}
				return pfound->val;
			} 
			if (!long_only || argv[optind][1] == '-'
#ifdef GETOPT_COMPAT
				|| argv[optind][0] == '+'
#endif
				|| my_index (optstring, *nextchar) == NULL)
			{
				if(opterr)
				{
					if (argv[optind][1] == '-')
						fprintf (stderr, "%s: unrecognized option `--%s'\n",argv[0], nextchar);
					else
						fprintf (stderr, "%s: unrecognized option `%c%s'\n",argv[0], argv[optind][0], nextchar);
				}
				nextchar = (char *) "";
				optind++;
				return BAD_OPTION;
			}
		}
		{
			char c = *nextchar++;
			char *temp = my_index (optstring, c);
			if (*nextchar == '\0')
				++optind;
			if (temp == NULL || c == ':')
			{
				if(opterr)
				{
#if 0
					if(c < 040 || c >= 0177)
						fprintf (stderr, "%s: unrecognized option, character code 0%o\n",argv[0], c);
					else 
						printf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
#else
					fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
#endif
				}
				optopt = c;
				return BAD_OPTION;
			}
			if(temp[1] == ':')
			{
				if (temp[2] == ':')
				{
					if (*nextchar != '\0')
					{
						optarg = nextchar;
						optind++;
					}
					else
						optarg = 0;
					nextchar = NULL;
				}
				else
				{
					if(*nextchar != '\0')
					{
						optarg = nextchar;
						optind++;
					}
					else if(optind == argc)
					{
						if(opterr)
						{
#if 0
							fprintf (stderr, "%s: option `-%c' requires an argument\n",argv[0], c);
#else
							fprintf (stderr, "%s: option requires an argument -- %c\n",argv[0], c);
#endif
						}
						optopt = c;
						if (optstring[0] == ':')
							c = ':';
						else
							c = BAD_OPTION;
					}
					else
						optarg = argv[optind++];
					nextchar = NULL;
				}
			}
			return c;
		}
	
}
int getopt(int argc,char *const *argv,const char *optstring)
{
	return _getopt_internal (argc, argv, optstring,(const struct option *) 0,(int *) 0,0);
}
int getopt_long(int argc,char *const *argv,const char *options,const struct option *long_options,int *opt_index)
{
	return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
#endif